package com.zyl.blog.processing.listen;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.zyl.blog.common.utils.Extreme.LogUtil;
import com.zyl.blog.processing.model.ExcelErrorData;
import com.zyl.blog.processing.model.ExcelImportResult;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.Accessors;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * @version v1.0
 * @ProjectName: Personal_Blog_Server
 * @Package: com.zyl.blog.processing.listen
 * @ClassName: ExcelDataListener
 * @Description: EasyExcel通用数据监听器
 * @Author FinalFantasy
 * @Date 2025/8/14-13:14
 */
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class ExcelDataListener<T> implements ReadListener<T> {

    /**
     * 批处理阈值
     */
    private static final int BATCH_COUNT = 100;

    /**
     * 缓存的数据列表
     */
    private List<T> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    /**
     * 导入结果
     */
    private ExcelImportResult<T> importResult = new ExcelImportResult<>();

    /**
     * 数据验证函数
     */
    private Function<T, String> validator;

    /**
     * 批处理消费者
     */
    private Consumer<List<T>> batchConsumer;

    /**
     * 构造函数
     * @param validator 数据验证函数，返回null表示验证通过
     * @param batchConsumer 批处理消费者
     */
    public ExcelDataListener(Function<T, String> validator, Consumer<List<T>> batchConsumer) {
        this.validator = validator;
        this.batchConsumer = batchConsumer;
    }

    /**
     * 每解析一行数据都会调用此方法
     */
    @Override
    public void invoke(T data, AnalysisContext context) {
        /* 行号从1开始 */
        int rowNum = context.readRowHolder().getRowIndex() + 1;
        importResult.setTotalCount(importResult.getTotalCount() + 1);

        /* 数据验证 */
        String errorMsg = validator.apply(data);
        if (errorMsg == null || errorMsg.isEmpty()) {
            /* 验证通过，加入缓存 */
            cachedDataList.add(data);
            importResult.setSuccessCount(importResult.getSuccessCount() + 1);

            /* 达到BATCH_COUNT，则进行批处理 */
            if (cachedDataList.size() >= BATCH_COUNT) {
                batchConsumer.accept(cachedDataList);
                /* 处理完成后清空列表 */
                cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
            }
        } else {
            /* 验证失败，记录错误信息 */
            ExcelErrorData<T> errorData = new ExcelErrorData<>();
            errorData.setRowNum(rowNum);
            errorData.setData(data);
            errorData.setErrorMessage(errorMsg);

            if (importResult.getErrorData() == null) {
                importResult.setErrorData(ListUtils.newArrayList());
            }
            importResult.getErrorData().add(errorData);
            importResult.setErrorCount(importResult.getErrorCount() + 1);
        }
    }

    /**
     * 所有数据解析完成后调用此方法
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        /* 处理剩余的数据 */
        if (!cachedDataList.isEmpty()) {
            batchConsumer.accept(cachedDataList);
        }
        LogUtil.info("Excel解析完成，总记录数: {}, 成功: {}, 失败: {}",
                importResult.getTotalCount(),
                importResult.getSuccessCount(),
                importResult.getErrorCount());
    }

    /**
     * 异常处理
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) {
        LogUtil.error("Excel解析异常", exception);
        // 可以在这里处理异常，例如记录错误行号等
    }
}
